package post

import (
	"gitee.com/hexug/vblog/tree/master/api/apps/tag"
	"github.com/bytedance/sonic"
	"strings"
	"time"
)

var (
	AppName = "post"
)

type CreateBlogRequest struct {
	Title   string `json:"title" gorm:"column:title;uniqueIndex:idx_title" validate:"required"`
	Author  string `json:"author" gorm:"column:author;not null" validate:"required"`
	Summary string `json:"summary" gorm:"column:summary;not null"`
	Content string `json:"content" gorm:"column:content"`
	Status  Status `json:"status" gorm:"column:status;not null"`
}

func (r Blog) String() string {
	b, err := sonic.Marshal(r)
	if err != nil {
		panic(err)
	}
	return string(b)
}
func NewCreateBlogRequest() *CreateBlogRequest {
	return &CreateBlogRequest{
		Status: DRAFT,
	}
}

type Blog struct {
	Id         int   `json:"id" gorm:"column:id;primaryKey;autoIncrement"`
	CreatedAt  int64 `json:"created_at" gorm:"column:created_at;not null"`
	UpdatedAt  int64 `json:"updated_at" gorm:"column:updated_at;not null"`
	PulishedAt int64 `json:"pulished_at" gorm:"column:pulished_at;not null"`
	*CreateBlogRequest
	TagList []*tag.Tag `json:"tag"`
}

func NewBlog(request *CreateBlogRequest) *Blog {
	t := time.Now().Unix()
	b := &Blog{
		CreateBlogRequest: request,
		CreatedAt:         t,
		UpdatedAt:         t,
		TagList:           []*tag.Tag{},
	}
	if request.Status == PUBLISHED {
		b.PulishedAt = t
	}
	return b
}

type UpdateBlogRequest struct {
	*CreateBlogRequest
	UpdateMod UpdateMod `json:"updateMod" validate:"lowercase"`
	Id        int       `json:"id" validate:"required"`
}

func NewUpdateBlogRequest() *UpdateBlogRequest {
	return &UpdateBlogRequest{
		UpdateMod: PATCH,
		CreateBlogRequest: &CreateBlogRequest{
			Status: DRAFT,
		},
	}
}

type DeleteOrGetBlogRequest struct {
	Id int `json:"id" validate:"required"`
}

func NewDeleteOrGetBlogRequest(id int) *DeleteOrGetBlogRequest {
	return &DeleteOrGetBlogRequest{
		Id: id,
	}
}

type QueryBlogRequest struct {
	PageSize int    `json:"page_size"`
	PageNum  int    `json:"page_num"`
	Keywords string `json:"keywords"`
	Status   Status `json:"status"`
}

func NewQueryBlogRequest() *QueryBlogRequest {
	return &QueryBlogRequest{}
}

type BlogsList struct {
	Total int64   `json:"total"`
	Items []*Blog `json:"items"`
}

func NewBlogsList() *BlogsList {
	return &BlogsList{
		//防止出现空指针
		Items: []*Blog{},
	}
}

// UpdateMod枚举
type UpdateMod string

const (
	PUT   UpdateMod = "put"
	PATCH UpdateMod = "patch"
)

// Status Status枚举
type Status int8

const (
	DRAFT Status = 1 + iota
	PUBLISHED
)

var StatusMap = map[Status]string{
	DRAFT:     "draft",
	PUBLISHED: "published",
}

func (s Status) MarshalJSON() ([]byte, error) {
	v, ok := StatusMap[s]
	if ok {
		return []byte(`"` + v + `"`), nil
	} else {
		return nil, nil
	}
}
func (s *Status) UnmarshalJSON(data []byte) error {
	str := string(data)
	str = strings.Trim(str, `"`)
	for k, v := range StatusMap {
		if v == strings.ToLower(str) {
			*s = k
			return nil
		}
	}
	return nil
}

func (s Status) String() string {
	v, ok := StatusMap[s]
	if ok {
		return `"` + v + `"`
	}
	return ""
}
